package org.zhouhe.util;

import java.io.StringWriter;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;

import ognl.OgnlException;
import ognl.OgnlRuntime;
import ognl.PropertyAccessor;

import org.apache.tiles.TilesApplicationContext;
import org.apache.tiles.context.TilesRequestContext;
import org.apache.tiles.context.TilesRequestContextFactory;
import org.apache.tiles.evaluator.AttributeEvaluatorFactory;
import org.apache.tiles.evaluator.BasicAttributeEvaluatorFactory;
import org.apache.tiles.evaluator.impl.DirectAttributeEvaluator;
import org.apache.tiles.locale.LocaleResolver;
import org.apache.tiles.ognl.ApplicationScopeNestedObjectExtractor;
import org.apache.tiles.ognl.DelegatePropertyAccessor;
import org.apache.tiles.ognl.NestedObjectDelegatePropertyAccessor;
import org.apache.tiles.ognl.OGNLAttributeEvaluator;
import org.apache.tiles.ognl.PropertyAccessorDelegateFactory;
import org.apache.tiles.ognl.RequestScopeNestedObjectExtractor;
import org.apache.tiles.ognl.SessionScopeNestedObjectExtractor;
import org.apache.tiles.ognl.TilesApplicationContextNestedObjectExtractor;
import org.apache.tiles.ognl.TilesContextPropertyAccessorDelegateFactory;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.zhouhe.modules.article.service.ArticleService;
import org.zhouhe.modules.hotproject.service.HotProjectService;
import org.zhouhe.modules.imageSlider.service.ImageSliderService;
import org.zhouhe.modules.industry.service.IndustryService;
import org.zhouhe.modules.report.service.ReportService;
import org.zhouhe.vo.ArticleType;
import org.zhouhe.vo.ImageSlider;
import org.zhouhe.vo.Industry;
import org.zhouhe.vo.Investment;
import org.zhouhe.vo.KeywordRecommended;
import org.zhouhe.vo.Region;
import org.zhouhe.vo.ReportType;

@SuppressWarnings("rawtypes")
public class InitSystem extends HttpServlet {

	private static final long serialVersionUID = 1662521323807475234L;
	private static WebApplicationContext wac;
	private static ServletContext servletContext;
	public static Map<String, String> paramMap = new HashMap<String, String>();
	public static final Map<Integer, ReportType> reportTypeMap = new HashMap<Integer, ReportType>();

	public InitSystem() {
		super();
	}

	public void destroy() {
		super.destroy(); // Just puts "destroy" string in log
	}

	@Override
	public void init(ServletConfig config) throws ServletException {
		servletContext = config.getServletContext();
		initparamMap();
		wac = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
		reloadIndustry();
		reloadArticleType();
		reloadReportForIndex();
		reloadRegions();
		reloadInvestments();
		reloadKeywordRecommned();
		reloadSliders();
	}
	public static void initparamMap(){
		Enumeration e = servletContext.getInitParameterNames();
		while(e.hasMoreElements()){
			String key = e.nextElement().toString();
			paramMap.put(key, servletContext.getInitParameter(key));
		}
		System.out.println("paramMap="+ paramMap);
	}

	public static void reloadIndustry() {
		IndustryService service = (IndustryService) wac.getBean("industryService");
		List<Industry> industryList = service.getIndustryTreeData();
		servletContext.setAttribute(Constant.APPLICATION_KEY_INDUSTRY_LIST, industryList);
		Document menuDoc = DocumentHelper.createDocument();
		Element menuRoot = menuDoc.addElement("tree").addAttribute("id", "0").addAttribute("text", "所有行业");
		
		for(Industry ind : industryList){
			Element item = menuRoot.addElement("item");
			item.addAttribute("id", ind.getIndustryId().toString());
			item.addAttribute("text", ind.getName());
			item.addAttribute("open", "1");
			for(Industry subInd : ind.getIndustries()){
				Element subItem = item.addElement("item");
				subItem.addAttribute("id", subInd.getIndustryId().toString());
				subItem.addAttribute("text", subInd.getName());
				subItem.addAttribute("open", "1");
			}
		}
		OutputFormat format = OutputFormat.createCompactFormat();
		format.setEncoding("UTF-8");
		StringWriter out = new StringWriter();
		XMLWriter xmlWriter = new XMLWriter(out, format);
		// 打印doc
		try {
			xmlWriter.write(menuDoc);
			xmlWriter.flush();
			String treeXmlStr = out.toString().trim();
			treeXmlStr = treeXmlStr.replace("\"", "\\\"");
			treeXmlStr = treeXmlStr.replace("\n", "");
			treeXmlStr = treeXmlStr.replace("\r", "");
			servletContext.setAttribute(Constant.APPLICATION_KEY_INDUSTRY_XML, treeXmlStr);
		} catch (Exception e) {

		}
	}

	public static void reloadArticleType() {
		ArticleService service = (ArticleService) wac.getBean("articleService");
		List<ArticleType> articleTypeList = service.getArticleTypeTreeData();
		servletContext.setAttribute(Constant.APPLICATION_KEY_ARTICLE_TYPE_LIST, articleTypeList);
		
		Document menuDoc = DocumentHelper.createDocument();
		Element menuRoot = menuDoc.addElement("tree").addAttribute("id", "0").addAttribute("text", "所有行业");
		
		for(ArticleType type : articleTypeList){
			Element item = menuRoot.addElement("item");
			item.addAttribute("id", type.getArticleTypeId().toString());
			item.addAttribute("text", type.getName());
			item.addAttribute("open", "1");
			for(ArticleType subType : type.getArticleTypes()){
				Element subItem = item.addElement("item");
				subItem.addAttribute("id", subType.getArticleTypeId().toString());
				subItem.addAttribute("text", subType.getName());
				subItem.addAttribute("open", "1");
			}
		}
		OutputFormat format = OutputFormat.createCompactFormat();
		format.setEncoding("UTF-8");
		StringWriter out = new StringWriter();
		XMLWriter xmlWriter = new XMLWriter(out, format);
		// 打印doc
		try {
			xmlWriter.write(menuDoc);
			xmlWriter.flush();
			String treeXmlStr = out.toString().trim();
			treeXmlStr = treeXmlStr.replace("\"", "\\\"");
			treeXmlStr = treeXmlStr.replace("\n", "");
			treeXmlStr = treeXmlStr.replace("\r", "");
			servletContext.setAttribute(Constant.APPLICATION_KEY_ARTICLE_TYPE_XML, treeXmlStr);
		} catch (Exception e) {

		}
	}

	/**
	 * 加载首页要显示的文章、报告到内存中：
	 */
	public static void reloadReportForIndex() {
		ReportService service = (ReportService) wac.getBean("reportService");
		List<ReportType> reportTypeList = service.getReportTypeList();
		servletContext.setAttribute(Constant.APPLICATION_KEY_REPORT_TYPE_LIST, reportTypeList);
		for (ReportType rt : reportTypeList) {
			reportTypeMap.put(rt.getReportTypeId(), rt);
			if (rt.getReportTypes() != null) {
				for (ReportType subRt : rt.getReportTypes()) {
					reportTypeMap.put(subRt.getReportTypeId(), subRt);
				}
			}
		}
	}
	public static void reloadRegions(){
		HotProjectService service = (HotProjectService) wac.getBean("hotProjectService");
		List<Region> regionList = service.getRegionList();
		servletContext.setAttribute(Constant.APPLICATION_KEY_REGION_LIST, regionList);
	}
	public static void reloadInvestments(){
		HotProjectService service = (HotProjectService) wac.getBean("hotProjectService");
		List<Investment> investmentList = service.getInvestmentList();
		servletContext.setAttribute(Constant.APPLICATION_KEY_INVESTMENT_LIST, investmentList);
	}
	public static void reloadKeywordRecommned(){
		ReportService service = (ReportService) wac.getBean("reportService");
		List<KeywordRecommended> keywordList = service.getKeyWordsRecommended(null);
		servletContext.setAttribute(Constant.APPLICATION_KEY_KEYWORDS_LIST, keywordList);
	}

	public static void reloadSliders(){
		ImageSliderService service = (ImageSliderService) wac.getBean("imageSliderService");
		List<ImageSlider> imageSliderList = service.getImageSliderList(null);
		servletContext.setAttribute(Constant.APPLICATION_KEY_SLIDER_LIST, imageSliderList);
	}
	protected AttributeEvaluatorFactory createAttributeEvaluatorFactory(TilesApplicationContext applicationContext,
			TilesRequestContextFactory contextFactory, LocaleResolver resolver) {
		try {
			PropertyAccessor objectPropertyAccessor = OgnlRuntime.getPropertyAccessor(Object.class);
			PropertyAccessor mapPropertyAccessor = OgnlRuntime.getPropertyAccessor(Map.class);
			PropertyAccessor applicationContextPropertyAccessor = new NestedObjectDelegatePropertyAccessor<TilesRequestContext>(
					new TilesApplicationContextNestedObjectExtractor(), objectPropertyAccessor);
			PropertyAccessor requestScopePropertyAccessor = new NestedObjectDelegatePropertyAccessor<TilesRequestContext>(
					new RequestScopeNestedObjectExtractor(), mapPropertyAccessor);
			PropertyAccessor sessionScopePropertyAccessor = new NestedObjectDelegatePropertyAccessor<TilesRequestContext>(
					new SessionScopeNestedObjectExtractor(), mapPropertyAccessor);
			PropertyAccessor applicationScopePropertyAccessor = new NestedObjectDelegatePropertyAccessor<TilesRequestContext>(
					new ApplicationScopeNestedObjectExtractor(), mapPropertyAccessor);
			PropertyAccessorDelegateFactory<TilesRequestContext> factory = new TilesContextPropertyAccessorDelegateFactory(objectPropertyAccessor,
					applicationContextPropertyAccessor, requestScopePropertyAccessor, sessionScopePropertyAccessor, applicationScopePropertyAccessor);
			PropertyAccessor tilesRequestAccessor = new DelegatePropertyAccessor<TilesRequestContext>(factory);
			OgnlRuntime.setPropertyAccessor(TilesRequestContext.class, tilesRequestAccessor);
		} catch (OgnlException e) {
			throw new RuntimeException("Cannot initialize OGNL evaluator", e);
		}

		BasicAttributeEvaluatorFactory attributeEvaluatorFactory = new BasicAttributeEvaluatorFactory(new DirectAttributeEvaluator());
		attributeEvaluatorFactory.registerAttributeEvaluator("MVEL", new OGNLAttributeEvaluator());
		return attributeEvaluatorFactory;
	}
}
